#include "sys_info.h"
#include <stdio.h>
#include <string.h>
#include <unistd.h>

//首先定义一个函数用于获取cpu时间片
///@brief 该函数用于获取当前的cpu时间和每一次进入的时间
///@param 该函数只用于sys_info中所以是static变量
///@return 返回值为一个cpu_time_t的结构体，存储了总共的时间片总和
static cpu_time_t get_cpu_times()
{
    //打开/proc/stat/文件读取时间片
    //采用标准io
    FILE* fp = fopen("/proc/stat","r");
    if (fp == NULL)
    {
        perror("fopen error...");
        return (cpu_time_t){0,0};  //返回一个数值都为0的结构体表示失败
    }
    
    //成功之后就读取该数据
    char msg[256];
    //打印文件第一行的数据到缓冲区
    fgets(msg,sizeof(msg),fp);

    //读取完毕立马关闭
    fclose(fp);

    //定义长整型变量来存储时间片
    /* user：用户态时间
       nice：低优先级用户态时间
       system：内核态时间
       idle：空闲时间
       iowait：I/O 等待时间
       irq：硬件中断时间
       softirq：软件中断时间 */


    long long user,nice,system,idle,iowait,irq,softirq;

    //扫描msg的值，按照格式分别赋值给上面的长整型变量
    sscanf(msg, "cpu %lld %lld %lld %lld %lld %lld %lld", 
        &user,&nice,&system,&idle,&iowait,&irq,&softirq);

    //返回结构体
    return (cpu_time_t){
        .total = user+nice+system+idle+iowait+irq+softirq,
        .idle = idle
    };
    
}

//获取时间利用率
double get_cpu_usage(void)
{
    //CPU 利用率的本质是：在单位时间内，CPU 用于非空闲状态的时间占比

    //首先定义一个初始的值为0，代表还没有使用cpu
    //这个变量应该是一个static类型的变量,确保只会被初始化一次
    static cpu_time_t prev_time = {0,0};
    double usage;
    long long idle_delta,total_delta;

    //获取当前的时间片信息
    cpu_time_t current_time = get_cpu_times();
    if (prev_time.total == 0)
    {
        prev_time = current_time;
        printf("当前为第一次调用cpu无法计算\n");
        return 0.0;
    }
        
        total_delta = current_time.total-prev_time.total;
        idle_delta = current_time.idle-prev_time.idle;

        prev_time = current_time;

        if (total_delta == 0) {
        return 0.0;
        }

        usage = (1.0 - (double)idle_delta / (double)total_delta) * 100.0;
    

    return usage;
}

//获取当前系统的内存信息
mem_info_t get_memory_info(void)
{
    //初始化结构体
    mem_info_t res = {0,0};
    FILE * fp = fopen("/proc/meminfo","r");
    if (fp == NULL)
    {
        perror("open meminfo error...");
        return (mem_info_t){0,0};
    }
    
    //从文件读取内存信息
    //获取fp中的memtotal和mem_available
    char msg[256];
    //按行的方式读取fp的数据后写入msg
    while (fgets(msg,sizeof(msg),fp))//fgets失败返回null或者errno
    {
        if (!(strncmp(msg,"MemTotal:",9)))
        {
            //扫描msg中"MemTotal:"格式的值，输入到res.total_kb
            sscanf(msg,"MemTotal: %lu kB ",&res.total_kb);
        }
        if (!(strncmp(msg,"MemAvailable:",13)))
        {
            sscanf(msg,"MemAvailable: %lu kB",&res.available_kb);
        }
        
    }
    
    


    fclose(fp);
    return res;

}

float get_cpu_temperature(void)
{
    //"thermal_zone0" 
    FILE* fp = fopen("/sys/class/thermal/thermal_zone0/temp", "r");

    if (fp == NULL)
    {
        perror("open error...");
        return -1;
    }
    int temp;
    fscanf(fp,"%d",&temp);

    fclose(fp);
    return (float)temp/1000.0f;
}